package p.s;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.net.URL;
import java.util.Enumeration;
import java.util.ArrayList;
import java.util.List;

/**
 * A class implementing this interface and named in
 * <code>"/META-INF/services/p.s.Init"</code> is instantiated and
 * called and then released.  A class member implementing the Init
 * interface and accessible by the {@link Init$Service} has a public
 * simple constructor taking no arguments, and is not abstract.
 */
public interface Init {
    /**
     * The init service reads each resource named
     * <code>"/META-INF/services/p.s.Init"</code> found in the server's
     * classpath, instantiating and intializing members of the Init
     * class found there.  That file is a list of classnames, one per
     * line -- no punctuation like commas.  Each line must be
     * terminated by a newline, LF (0x0A) or CRLF (0x0D, 0x0A).
     */
    public final class Service 
        extends ArrayList<Init>
        implements Init
    {

        public Service(){
            super();
            java.lang.ClassLoader loader = this.getClass().getClassLoader();
            try {
                Enumeration<URL> sources = loader.getResources("META-INF/services/p.s.Init");
                while (sources.hasMoreElements()){
                    URL source = sources.nextElement();
                    try {
                        BufferedReader reader = new BufferedReader(new InputStreamReader(source.openStream()));
                        try {
                            String classname;
                            while (null != (classname = reader.readLine())){
                                classname = classname.trim();
                                try {
                                    Class clas = Class.forName(classname);
                                    if (Init.class.isAssignableFrom(clas) && (!Service.class.equals(clas))){
                                        Init init = (Init)clas.newInstance();
                                        this.add(init);
                                    }
                                }
                                catch (Exception exc){
                                    exc.printStackTrace();
                                }
                            }
                        }
                        finally {
                            reader.close();
                        }
                    }
                    catch (IOException ignore){
                    }
                }
            }
            catch (IOException ignore){
            }
        }


        public void init(Server server){
            for (Init instance : this){
                instance.init(server);
                System.out.println("Initialized "+instance.getClass().getName());
            }
        }
    }

    public void init(Server server);

}
